Ahmet Mahmut Gokkaya
Blog Books

Step 1: Set Parameters and Download Data¶

In [2]:
import numpy as np
import pandas as pd
import datetime as dt
import yfinance as yf

# Set the number of years for historical data
years = 15

# Define the end and start dates
endDate = dt.datetime.now()
startDate = endDate - dt.timedelta(days=365 * years)

# Create a list of tickers
tickers = ['SPY', 'AAPL', 'GLD', 'NVDA', 'TSLA']

# Download the daily adjusted close prices for the tickers
adj_close_df = pd.DataFrame()
for ticker in tickers:
    data = yf.download(ticker, start=startDate, end=endDate)
    adj_close_df[ticker] = data['Adj Close']

# Display the downloaded data
print(adj_close_df)
[*********************100%%**********************]  1 of 1 completed
[*********************100%%**********************]  1 of 1 completed
[*********************100%%**********************]  1 of 1 completed
[*********************100%%**********************]  1 of 1 completed
[*********************100%%**********************]  1 of 1 completed
                   SPY        AAPL         GLD        NVDA        TSLA
Date                                                                  
2009-07-01   69.827072    4.312715   92.389999    0.260034         NaN
2009-07-02   67.921249    4.227867   91.250000    0.249944         NaN
2009-07-06   67.913666    4.185293   90.760002    0.241919         NaN
2009-07-07   66.597740    4.088368   90.709999    0.231371         NaN
2009-07-08   66.552353    4.143321   89.269997    0.231829         NaN
...                ...         ...         ...         ...         ...
2024-06-21  544.510010  207.490005  214.779999  126.570000  183.009995
2024-06-24  542.739990  208.139999  215.630005  118.110001  182.580002
2024-06-25  544.830017  209.070007  214.559998  126.089996  187.350006
2024-06-26  545.510010  213.250000  212.580002  126.400002  196.369995
2024-06-27  545.909973  213.259903  215.300003  123.867996  195.970001

[3773 rows x 5 columns]

This code sets the time period for historical data, defines a list of tickers, and downloads their daily adjusted close prices from Yahoo Finance.¶

Step 2: Calculate Daily Log Returns¶

In [3]:
# Calculate the daily log returns and drop any NAs
log_returns = np.log(adj_close_df / adj_close_df.shift(1))
log_returns = log_returns.dropna()

# Display the log returns
print(log_returns)
                 SPY      AAPL       GLD      NVDA      TSLA
Date                                                        
2010-06-30 -0.009546 -0.018279  0.003375 -0.026101 -0.002515
2010-07-01 -0.004466 -0.012200 -0.038879  0.016513 -0.081723
2010-07-02 -0.005465 -0.006217  0.012313 -0.012603 -0.134312
2010-07-06  0.006534  0.006820 -0.016851 -0.010790 -0.175470
2010-07-07  0.031010  0.039587  0.010417  0.047192 -0.019431
...              ...       ...       ...       ...       ...
2024-06-21 -0.001342 -0.010499 -0.015615 -0.032721  0.007899
2024-06-24 -0.003256  0.003128  0.003950 -0.069179 -0.002352
2024-06-25  0.003843  0.004458 -0.004975  0.065380  0.025790
2024-06-26  0.001247  0.019796 -0.009271  0.002456  0.047022
2024-06-27  0.000733  0.000046  0.012714 -0.020235 -0.002039

[3522 rows x 5 columns]

Step 3: Define Functions for Expected Return and Standard Deviation¶

In [5]:
# Function to calculate portfolio expected return
def expected_return(weights, log_returns):
    return np.sum(log_returns.mean() * weights)

# Function to calculate portfolio standard deviation
def standard_deviation(weights, cov_matrix):
    variance = weights.T @ cov_matrix @ weights
    return np.sqrt(variance)

Step 4: Calculate Covariance Matrix¶

This step calculates the covariance matrix of the log returns.¶

In [6]:
# Create a covariance matrix for all the securities
cov_matrix = log_returns.cov()

# Display the covariance matrix
print(cov_matrix)
           SPY      AAPL       GLD      NVDA      TSLA
SPY   0.000116  0.000130  0.000005  0.000189  0.000166
AAPL  0.000130  0.000310  0.000008  0.000245  0.000227
GLD   0.000005  0.000008  0.000095  0.000003  0.000014
NVDA  0.000189  0.000245  0.000003  0.000797  0.000367
TSLA  0.000166  0.000227  0.000014  0.000367  0.001270

Step 5: Calculate Portfolio Expected Return and Standard Deviation¶

This part creates an equally weighted portfolio and calculates its expected return and standard deviation.¶

In [7]:
# Create an equally weighted portfolio
portfolio_value = 1000000
weights = np.array([1 / len(tickers)] * len(tickers))

# Calculate the portfolio's expected return and standard deviation
portfolio_expected_return = expected_return(weights, log_returns)
portfolio_std_dev = standard_deviation(weights, cov_matrix)

Step 6: Define Random Z-Score Function¶

This function generates a random z-score, which is a critical component of the Monte Carlo simulation.¶

In [9]:
# Function to generate a random z-score from a normal distribution
def random_z_score():
    return np.random.normal(0, 1)

Step 7: Define Scenario Gain/Loss Function¶

This function calculates the portfolio gain or loss for a given scenario.¶

In [10]:
# Number of days to projectT
days = 20

# Function to calculate scenario gain/loss
def scenario_gain_loss(portfolio_value, portfolio_std_dev, z_score, days):
    return portfolio_value * portfolio_expected_return * days + portfolio_value * portfolio_std_dev * z_score * np.sqrt(days)

Step 8: Run Monte Carlo Simulations¶

This code runs 10,000 Monte Carlo simulations to project possible future portfolio values.¶

In [11]:
# Number of simulatIons
simulations = 10000
scenarioReturn = []

# Run the simulatIons
for i in range(simulations):
    z_score = random_z_score()
    scenarioReturn.append(scenario_gain_loss(portfolio_value, portfolio_std_dev, z_score, days))

Step 9: Calculate Value at Risk (VaR)¶

This step calculates the Value at Risk (VaR) at a 99% confidence level based on the simulation results.¶

YOU SHOULD CHANGE DAYS AND CONFİDENCE LEVEL BECAUSE U WILL SEE DIFFERENCE BETWEEN THEM, HOW THEY EFFECT THE VaR RESULTS.

In [12]:
# Specify a confidence interval
confidence_interval = 0.99

# Calculate Value at Risk (VaR)
VaR = -np.percentile(scenarioReturn, 100 * (1 - confidence_interval))

# Display the VaR
print(f'Value at Risk (VaR) at {confidence_interval:.0%} confidence level: ${VaR:.2f}')
Value at Risk (VaR) at 99% confidence level: $126056.07

Value at Risk (VaR) at 99% confidence level: $126056.07¶

Step 10: Plot Results¶

This code visualizes the distribution of portfolio gains/losses over the simulated period and highlights the VaR.¶

By following these steps, you can implement a Monte Carlo simulation to calculate the VaR for a given portfolio.¶

In [13]:
import matplotlib.pyplot as plt

# Plot the results of all 10,000 scenarios
plt.hist(scenarioReturn, bins=50, density=True)
plt.xlabel('Scenario Gain/Loss ($)')
plt.ylabel('Frequency')
plt.title(f'Distribution of Portfolio Gain/Loss Over {days} Days')
plt.axvline(-VaR, color='r', linestyle='dashed', linewidth=2, label=f'VaR at {confidence_interval:.0%} confidence level')
plt.legend()
plt.show()
No description has been provided for this image
  • gokkaya[thiswebsite]
  • ahmetmahmutgokkaya
  • Profile Icon ahmetmahmutgokkaya
  • ahmetmahmutgokkaya